
using System.Collections.ObjectModel;
using System.IO;
using System.Net.Sockets;
using System.Net;
using MeasureAbstract.IMotionDevice;
using System.IO.Ports;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Windows;
using Org.BouncyCastle.Utilities;
using System.Security.AccessControl;

namespace 长屏滑台_一维
{
    public partial class Turntable : IMotionDevice
    {


        #region
        public Turntable()
        {
            Config = new MotionDeviceConfig();
            //设置支持的通信方式
            Config.CommunicationList = new ObservableCollection<CommunicationMode>()
            {
                new CommunicationMode() {Name="UART",Selected=true,Support=true},
            };
            //设置默认通信参数
            Config.LocalIP = "10.0.0.20";
            Config.LocalPort = "8080";
            Config.DestIP = "10.0.0.100";
            Config.DestPort = "8080";
            Config.PortName = "COM1";
            Config.BandRate = "38400";
            Config.ShowTCP = false;
            Config.ShowUART = true;

            //设置轴
            if (Config.Axes == null)
            {
                Config.Axes = new System.Collections.ObjectModel.ObservableCollection<Axis>();
            }
            Config.Axes.Clear();
            Config.Axes.Add(new Axis() { AxisID = 1, AxisName = "方位轴", Accuracy = 0.01, SupportPulseOut = false });



            AnalyzeData_Func = AnalyzeData;
            Timer = new System.Timers.Timer();
            Timer.Interval = 250;
            Timer.Elapsed += Timer_Elapsed;
        }

        private int AnalyzeData(byte[] data)
        {




            byte[] POS = new byte[4];
            POS[0] = data[4];
            POS[1] = data[3];
            POS[2] = data[6];
            POS[3] = data[5];
            if (Config != null)
            {
                if (Config.Axes != null)
                {
                    if (Config.Axes[0] != null)
                    {
                        Config.Axes[0].CurrentPosition = BitConverter.ToInt32(POS, 0) / 1000d;
                    }
                }
            }

            return 0;
        }

        public override string Name => "滑台";

        public override string Vender => "长屏";


        public override string Model => "一维滑台";

        public override string Description => "航天长屏测量静区性能时用的设备";


        public override MotionDeviceConfig? Config { get; set; }



        #endregion


        System.Timers.Timer? Timer;
        int a = 0;
        private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
        {
            byte[] cache = new byte[256];

            if (a%2==0)
            {
                byte[] Cmd = new byte[8] { 0x01, 0x03, 0x04, 0x62, 0x00, 0x02, 0x00, 0x00 };
                UInt16 CRC = CRCCMD(Cmd, 0, 5);
                byte[] temps = BitConverter.GetBytes(CRC);
                Cmd[6] = temps[0];
                Cmd[7] = temps[1];
                //询问位置
                if (Config != null)
                {
                    if (Config.Axes != null)
                    {
                        foreach (var temp in Config.Axes)
                        {
                            if (SerialPort.IsOpen)
                            {
                                SerialPort.ReadExisting();
                                SendData(Cmd);
                            }
                        }
                    }
                }
            }
            else
            {
                if(SerialPort.IsOpen)
                {
                    SerialPort.Read(cache, 0, SerialPort.BytesToRead);
                    if (cache[0] == 0x01 && cache[1] == 0x03 && cache[2] == 0x04)
                    {
                        UInt16 CRC = CRCCMD(cache, 0,  6);
                        byte[] temps = BitConverter.GetBytes(CRC);
                        if (cache[7] == temps[0] && cache[8] == temps[1])
                        {
                            //解析一条指令

                            AnalyzeData_Func?.Invoke(cache);
                        }
                    }
                }
            }
            a++;
            if(a==int.MaxValue)
            {
                a = 0;
            }
        }


        #region 数据收发
        TcpClient? TCPClient;
        UdpClient? UdpClient;
        IPEndPoint RemoteEndPoint;
        SerialPort? SerialPort;
        Thread Thread;
        private NetworkStream stream;
        public object HeartBeatFlag = false;
        [ObservableProperty]
        private bool heartBeatEnable = true;
        public Func<byte[], int> AnalyzeData_Func;

        public override void Connect()
        {
            string SelectedCommunication = "";
            foreach (var temp in Config.CommunicationList)
            {
                if (temp.Selected)
                {
                    SelectedCommunication = temp.Name;
                }
            }
            // 创建一个CancellationTokenSource，用于取消连接操作
            CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();

            if (!ConnectState)
            {
                switch (SelectedCommunication.ToUpper())
                {
                    case "TCP":
                        //TCPClient = new TcpClient();
                        //Task ConnectTask = TCPClient.ConnectAsync(Config.DestIP, int.Parse(Config.DestPort), CancellationTokenSource.Token).AsTask();

                        //// 设置连接超时时间为5秒
                        //Task TimeoutTask = Task.Delay(1000);

                        //// 使用Task.WhenAny等待连接完成或超时
                        //Task CompletedTask = await Task.WhenAny(ConnectTask, TimeoutTask);

                        //// 如果连接完成任务是连接任务，则连接成功
                        //if (CompletedTask == ConnectTask)
                        //{
                        //    stream = TCPClient.GetStream();
                        //    ConnectState = true;
                        //    //开启接收线程
                        //    while (!TCPClient.Connected) ;
                        //    Thread = new Thread(TCPReceive);
                        //    Thread.Start();
                        //    while (Thread.ThreadState != ThreadState.Running)
                        //    {

                        //    }

                        //}
                        //else
                        //{
                        //    CancellationTokenSource.Cancel();
                        //    TCPClient.Close();
                        //    ConnectState = false;
                        //    throw new Exception($"{Vender}_{Model}TCP连接超时!");
                        //}


                        TCPClient = new TcpClient();
                        IAsyncResult ConnResult = TCPClient.BeginConnect(Config.DestIP, int.Parse(Config.DestPort), null, null);

                        ConnResult.AsyncWaitHandle.WaitOne(1000, true);

                        if (!ConnResult.IsCompleted)
                        {
                            TCPClient.Close();
                            ConnectState = false;
                            throw new Exception($"{Vender}_{Model}TCP连接超时!");
                        }
                        else
                        {
                            stream = TCPClient.GetStream();
                            ConnectState = true;
                            //开启接收线程
                            Thread = new Thread(TCPReceive);
                            Thread.Start();
                            while (Thread.ThreadState != ThreadState.Running)
                            {

                            }
                        }




                        //TCPClient = new TcpClient();
                        //TCPClient.Connect(Config.DestIP, int.Parse(Config.DestPort));
                        //stream = TCPClient.GetStream();
                        //ConnectState = true;
                        ////开启接收线程
                        //while (!TCPClient.Connected) ;
                        //Thread = new Thread(TCPReceive);
                        //Thread.Start();
                        //while (Thread.ThreadState != ThreadState.Running)
                        //{

                        //}
                        break;
                    case "UDP":
                        UdpClient = new UdpClient();
                        //UdpClient.Client.Bind(new IPEndPoint(IPAddress.Parse(Config.LocalIP), int.Parse(Config.LocalPort)));
                        RemoteEndPoint = new IPEndPoint(IPAddress.Parse(Config.DestIP), int.Parse(Config.DestPort));
                        UdpClient.Connect(RemoteEndPoint);
                        ConnectState = true;
                        //开启接收线程
                        Thread = new Thread(UDPReceive);
                        Thread.Start();
                        while (Thread.ThreadState != ThreadState.Running)
                        {

                        }
                        break;
                    case "UART":
                        SerialPort = new SerialPort();
                        SerialPort.PortName = Config.PortName;
                        SerialPort.BaudRate = int.Parse(Config.BandRate);
                        SerialPort.Open();
                        ConnectState = true;
                        //开启接收线程
                        //Thread = new Thread(UARTReceive);
                        //Thread.Start();
                        //while (Thread.ThreadState != ThreadState.Running)
                        //{

                        //}
                        break;
                    case "GPIB":
                        throw new NotImplementedException();
                    case "USB":
                        throw new NotImplementedException();
                    default:
                        throw new NotImplementedException();
                }
                Timer.Start();
            }
            else
            {
                //已经处于连接状态，不进行操作
            }
        }
        private void UARTReceive(object? obj)
        {
            int cachelenth = 128;
            byte[] cache = new byte[cachelenth];
            int Count = 0;
            Array.Clear(cache, 0, cache.Length);
            byte[] DataItem = new byte[9];
            while (true)
            {
                try
                {

                    if (!SerialPort.IsOpen)
                    {
                        Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}串口连接断开!"); });
                        break;
                    }
                    if (SerialPort.BytesToRead > 0)
                    {
                        cache[Count] = (byte)SerialPort.ReadByte();
                        Count++;
                        //检索有效指令
                        bool done = false;
                        while (!done)
                        {
                            if (Count < 9)
                            {
                                done = true;
                                break;
                            }
                            int cmdcount = 0;
                            int index = 0;
                            for (int i = 0; i < cachelenth-8; i++)
                            {
                                if (cache[i] == 0x01 && cache[i + 1] == 0x03 && cache[i + 2] == 0x04)
                                {
                                    UInt16 CRC = CRCCMD(cache, i, i + 6);
                                    byte[] temps = BitConverter.GetBytes(CRC);
                                    if (cache[i + 7] == temps[0] && cache[i + 8] == temps[1])
                                    {
                                        //解析一条指令
                                        for (int j = 0; j < 9; j++)
                                        {
                                            DataItem[j] = cache[i + j];
                                        }
                                        AnalyzeData_Func?.Invoke(DataItem);
                                        cmdcount++;
                                        index = i+8;
                                        i=i + 8;
                                    }
                                }
                            }
                            //前移
                            if(cmdcount>0)
                            {
                                if(cachelenth<=(index+1))
                                {
                                    //恰好用完，清空
                                    Count = 0;
                                    Array.Clear(cache, 0, cache.Length);
                                }
                                else
                                {
                                    if (Count == (index + 1))
                                    {
                                        //最后一个字节恰好被处理了
                                        Count = 0;
                                        Array.Clear(cache, 0, cache.Length);
                                    }
                                    else
                                    {
                                        //被处理的最后一个字节后面还有未处理的字节，移到开头
                                        for (int i = 0; i < Count - index - 1; i++)
                                        {
                                            cache[i] = cache[index + 1 + i];
                                        }
                                    }
                                }
                            }
                            //解析完，并且前移后，发现剩余的字节数大于9，说明这些数据不是一个完整的指令，都是坏值，删除
                            if (Count >= 9)
                            {
                                Count = 0;
                                Array.Clear(cache, 0, cache.Length);
                            }
                        }
                    }
                }
                catch (Exception e)
                {

                    DisConnect();
                    //Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}串口连接断开,{e.Message}"); });
                    Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}串口连接断开!{e.Message}"); });
                    break;
                }
            }
        }

        private void UDPReceive(object? obj)
        {
            while (true)
            {
                try
                {
                    byte[] receivedData = UdpClient.Receive(ref RemoteEndPoint);
                    try
                    {
                        AnalyzeData_Func?.Invoke(receivedData);
                    }
                    catch
                    {
                        //数据错误不处理
                    }
                }
                catch (Exception e)
                {

                    DisConnect();
                    //Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}UDP连接断开,{e.Message}"); });
                    Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}UDP连接断开!"); });
                    break;
                }
            }
        }

        private void TCPReceive(object? obj)
        {
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[1024];
                    if (stream.CanRead)
                    {
                        int bytesRead = stream.Read(buffer, 0, buffer.Length);
                        Array.Resize(ref buffer, bytesRead);
                        try
                        {
                            AnalyzeData_Func?.Invoke(buffer);
                        }
                        catch
                        {
                            //数据错误不处理
                        }
                    }
                }
                catch (IOException e)
                {

                    DisConnect();
                    //Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}TCP连接断开,{e.Message}"); });
                    Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}TCP连接断开!"); });
                    break;
                }
            }
        }

        public override void DisConnect()
        {
            string SelectedCommunication = "";
            foreach (var temp in Config.CommunicationList)
            {
                if (temp.Selected)
                {
                    SelectedCommunication = temp.Name;
                }
            }
            if (ConnectState)
            {
                switch (SelectedCommunication.ToUpper())
                {
                    case "TCP":
                        stream.Close();
                        TCPClient?.Close();
                        ConnectState = false;
                        break;
                    case "UDP":
                        UdpClient?.Close();
                        ConnectState = false;
                        break;
                    case "UART":
                        SerialPort?.Close();
                        ConnectState = false;
                        break;
                    case "GPIB":
                        throw new NotImplementedException();
                    case "USB":
                        throw new NotImplementedException();
                    default:
                        throw new NotImplementedException();
                }
                Timer.Stop();
            }
            else
            {
                //已经处于关闭状态,不进行操作
            }
        }

        public virtual int SendData(byte[] Data)
        {
            string SelectedCommunication = "";
            foreach (var temp in Config.CommunicationList)
            {
                if (temp.Selected)
                {
                    SelectedCommunication = temp.Name;
                }
            }
            if (ConnectState)
            {
                switch (SelectedCommunication.ToUpper())
                {
                    case "TCP":
                        stream.Write(Data, 0, Data.Length);
                        break;
                    case "UDP":
                        //UdpClient?.Send(Data, Data.Length, RemoteEndPoint);
                        UdpClient?.Send(Data, Data.Length);
                        break;
                    case "UART":
                        SerialPort?.Write(Data, 0, Data.Length);
                        break;
                    case "GPIB":
                        throw new NotImplementedException();
                    case "USB":
                        throw new NotImplementedException();
                    default:
                        throw new NotImplementedException();
                }
            }
            else
            {
                Application.Current.Dispatcher.BeginInvoke(() => { throw new Exception($"{Vender}_{Model}未连接!"); });
            }
            return 0;
        }

        public override void HeartBeat(ref object ResponseFlag, int MaxResponseTime_ms)
        {

        }
        #endregion




        public override int Enable(int AxisID)
        {
            return 1;

        }
        public override int Disable(int AxisID)
        {
            return 1;


        }
        public override int Run(int AxisID, double Position, double Speed, double Acc, double Dcc, bool AbsoluteMovement = true)
        {
            byte[] Cmd = new byte[17];
            Cmd[0] = 0x01;
            Cmd[1] = 0x10;
            Cmd[2] = 0x00;
            Cmd[3] = 0x14;
            Cmd[4] = 0x00;
            Cmd[5] = 0x04;
            Cmd[6] = 0x08;


            //4字节速度
            int SP = Convert.ToInt32(Speed * 60);
            byte[] temps = BitConverter.GetBytes(SP);
            Cmd[7] = temps[1];
            Cmd[8] = temps[0];
            Cmd[9] = temps[3];
            Cmd[10] = temps[2];

            if (Config != null)
            {
                if (Config.Axes != null)
                {
                    if (Config.Axes[0] != null)
                    {
                        //设置伪速度
                        //Config.Axes[0].CurrentSpeed = Speed;
                    }
                }
            }

            //4字节位置
            int POS = Convert.ToInt32((Position - Config.Axes[0].CurrentPosition) * 1000) ;
            temps = BitConverter.GetBytes(POS);
            Cmd[11] = temps[1];
            Cmd[12] = temps[0];
            Cmd[13] = temps[3];
            Cmd[14] = temps[2];


            //2字节校验
            UInt16 CRC = CRCCMD(Cmd, 0, 14);
            temps = BitConverter.GetBytes(CRC);
            Cmd[15] = temps[0];
            Cmd[16] = temps[1];

            SendData(Cmd);
            return 0;
        }


        public UInt16 CRCCMD(byte[] Data, int StartIndex, int EndIndex)
        {
            //ushort crc = 0xFFFF; // 初始化 CRC 寄存器为 0xFFFF

            //for (int i = StartIndex; i < EndIndex+1; i++)
            //{
            //    crc ^= (ushort)(Data[i] << 8); // 将数据字节与 CRC 寄存器高位进行异或操作

            //    for (int j = 0; j < 8; j++)
            //    {
            //        if ((crc & 0x8000) != 0) // 如果 CRC 寄存器高位为 1，则进行异或操作
            //        {
            //            crc = (ushort)((crc << 1) ^ 0x1021);
            //        }
            //        else // 如果 CRC 寄存器高位为 0，则直接左移一位
            //        {
            //            crc <<= 1;
            //        }
            //    }
            //}

            //return crc;


            ushort crc = 0xFFFF; // 初始化 CRC 寄存器为 0xFFFF

            for (int i = StartIndex; i < EndIndex+1; i++)
            {
                crc ^= Data[i]; // 将数据字节与 CRC 寄存器进行异或操作

                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 0x0001) != 0) // 如果 CRC 寄存器最低位为 1，则进行右移和异或操作
                    {
                        crc = (ushort)((crc >> 1) ^ 0xA001);
                    }
                    else // 如果 CRC 寄存器最低位为 0，则直接右移一位
                    {
                        crc >>= 1;
                    }
                }
            }

            return crc;
        }
        public override int Stop(int AxisID)
        {
            byte[] Cmd = new byte[11];
            Cmd[0] = 0x01;
            Cmd[1] = 0x10;
            Cmd[2] = 0x03;
            Cmd[3] = 0xE8;
            Cmd[4] = 0x00;
            Cmd[5] = 0x01;
            Cmd[6] = 0x02;
            Cmd[7] = 0x00;
            Cmd[8] = 0x0B;

            //2字节校验
            UInt16 CRC = CRCCMD(Cmd, 0, 8);
            byte[] temps = BitConverter.GetBytes(CRC);
            Cmd[9] = temps[0];
            Cmd[10] = temps[1];




            SendData(Cmd);
            Thread.Sleep(200);
            SendData(Cmd);
            return 0;
        }

        public override void ReSet()
        {
            return;
        }

        public override bool ReachedState(int AxisID)
        {
            throw new NotImplementedException();
        }

        public override int TriggerOpen(int AxisID, double StartPosition, double EndPosition, double Interval, int PuslseWidth_us)
        {
            return 1;

        }

        public override int TriggerClose(int AxisID)
        {
            return 1;

        }

        public override int TriggerOne(int AxisID)
        {
            return 1;

        }
    }

}
